﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Navigation;
using GalaSoft.MvvmLight.Command;
using MishraReader.Entities;
using MishraReader.Entities.ShareServices;
using MishraReader.Services;
using MishraReader.ViewModels.Base;
using MetroLog;

namespace MishraReader.ViewModels.Settings.Options
{
    public class FacebookConfigurationViewModel : DialogViewModelBase, IShareServiceConfigurationViewModel
    {
        private static readonly ILogger Log = LogManagerFactory.DefaultLogManager.GetLogger<FacebookConfigurationViewModel>();
        private readonly IWpfApplication _application;
        private readonly IErrorService _errorService;
        private readonly IFacebookApi _facebookApi;

        private Uri _loginUri;

        private bool _userInputRequired;

        public FacebookConfigurationViewModel(IErrorService errorService,
                                              IWpfApplication application,
                                              IFacebookApi facebookApi)
        {
            _errorService = errorService;
            _application = application;
            _facebookApi = facebookApi;

            _facebookApi.AppId = FacebookShareService.AppID;
            _facebookApi.AppSecret = FacebookShareService.AppSecret;

            NavigatedCommand = new RelayCommand<NavigationEventArgs>(OnNavigated);
        }

        public Uri LoginUri
        {
            get { return _loginUri; }
            private set
            {
                Set(ref _loginUri, value);
            }
        }

        public ICommand NavigatedCommand { get; private set; }
        public IServiceAccountViewModel ServiceAccountViewModel { get; set; }

        public bool UserInputRequired
        {
            get { return _userInputRequired; }
            private set
            {
                Set(ref _userInputRequired, value);
            }
        }

        public void Configure()
        {
            var extendedPermissions = new[] {"publish_stream"};

            var parameters = new Dictionary<string, object>
                                 {
                                     {"response_type", "code"},
                                     {"display", "popup"}
                                 };

            if (extendedPermissions.Length > 0)
            {
                var scope = new StringBuilder();
                scope.Append(string.Join(",", extendedPermissions));
                parameters["scope"] = scope.ToString();
            }

            LoginUri = _facebookApi.GetLoginUrl(parameters);
            UserInputRequired = true;
            ShowData = true;
        }

        public void Disconnect()
        {
            Reset();
        }

        protected override void OnDialogClosed(bool? result)
        {
            base.OnDialogClosed(result);

            Reset();
        }

        private async void OnNavigated(NavigationEventArgs e)
        {
            try
            {
                IFacebookResult result;

                if (_facebookApi.TryParseResult(e.Uri, out result))
                {
                    UserInputRequired = false;
                    if (result.IsSuccess)
                    {
                        try
                        {
                            var token = await _facebookApi.ExchangeCodeForAccessTokenAsync(result.Code);
                            
                            if (ServiceAccountViewModel.SaveChangesToken(token))
                            {
                                ServiceAccountViewModel.IsActivated = true;
                                ExecuteOkayCommand();
                            }

                        }
                        catch(OperationCanceledException)
                        {
                            ServiceAccountViewModel.IsActivated = false;
                            _errorService.DisplayErrorMessage(Strings.UnableToConnectToFacebook);
                            
                            throw;
                        }
                        catch(Exception ex)
                        {
                            Log.Fatal("Unable to connect to Facebook", ex);
                        }
                    }
                    else
                    {
                        _errorService.DisplayErrorMessage(Strings.UnableToConnectToFacebook);
                    }
                }
                else
                {
                    UserInputRequired = _facebookApi.AdditionalInputRequired(e.Uri);
                }
            }
            catch (Exception ex)
            {
                Log.Error("WebBrowserNavigated", ex);
                _errorService.HandleException(ex);
            }
        }

        private void Reset()
        {
            UserInputRequired = true;
            LoginUri = null;
        }
    }
}